(Polymorphism) Addition parameter pass to constructor of derived class in factory pattern - oop

In factory pattern, we use a Factory class to produce a Product class that implement Abstract Product.
interface AbstractProduct {
public string getDetail();
}
class Product_A : AbstractProduct {
public string getDetail();
}
class Product_B : AbstractProduct {
public string getDetail();
}
class Factory {
public AbstractProduct produce(int product_id){
if (product_id == 1){
return Product_A();
}
else if (product_id == 2){
return Product_B();
}
}
}
int main() {
Factory factory = new Factory();
int id; // a random number either 1 or 2
print(factory.produce(id).getDetail());
}
My question is, what if today we need extract information to pass into Product_B from main(), for example a reference of a class instance.
int main() {
// object that need to be passed into Product_B
Database database = new Database();
Factory factory = new Factory();
int id; // a random number either 1 or 2
print(factory.produce(id).getDetail());
}
class Product_B : AbstractProduct {
public string getDetail() {
// I need the reference of database here.
// I'm unable to instance a database in side Product_B.
// I need to somehow pass it into Product_B.
database.query();
}
}
The only solution come to my mind is...
class Factory {
// pass the reference here
public AbstractProduct produce(int product_id, Database db){
if (product_id == 1){
return Product_A();
}
else if (product_id == 2){
return Product_B(db);
}
}
}
Is there any good solution or relative design pattern can solve this problem Elegant and Clean ? Thanks a lot.

The downside with your solution is that, every client of the Factory must have a Database in order to call the produce method.
So you can use the Abstract Factory pattern here:
interface AbstractFactory {
AbstractProduct produce();
}
class Factory_A implements AbstractFactory {
AbstractProduct produce() { return new Product_A(); }
}
class Factory_B implements AbstractFactory {
private Database db;
public Factory_B(Database db) { this.db = db; }
AbstractProduct produce() { return new Product_B(db); }
}
class Client {
private AbstractFactory factory;
public Client(AbstractFactory factory) { this.factory = factory; }
public void foo() {
AbstractProduct product = factory.produce();
// ...
}
}
void main() {
AbstractFactory factory = random() == 1 ?
new Factory_A() :
new Factory_B(new Database(...));
print(factory.produce().getDetail());
Client client = new Client(factory);
client.foo();
}
Hope this helps.

Related

Tweak jackson polymorphic deserialization

I have a simple polymorphic model like this
public class Foo {
private Bar bar1;
private Bar bar2;
public Bar getBar1() {
return bar1;
}
public Bar getBar2() {
return bar2;
}
public void setBar1(Bar bar1) {
this.bar1 = bar1;
}
public void setBar2(Bar bar2) {
this.bar2 = bar2;
}
}
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "#type")
public class Bar {
}
public class BarExpression extends Bar {
private String expression;
public String getExpression() {
return expression;
}
#JsonIgnore
public Object getValue() {
return null;
}
public void setExpression(String expression) {
this.expression = expression;
}
}
public class BarLiteral extends Bar {
private String value;
private String type;
public String getType() {
return type;
}
public Object getValue() {
return value;
}
public void setType(String type) {
this.type = type;
}
public void setValue(String value) {
this.value = value;
}
}
Serializing a simple example like this
public void run() throws Exception {
Foo foo;
BarLiteral bar1;
BarExpression bar2;
//
foo = new Foo();
bar1 = new BarLiteral();
bar1.setType("java.lang.String");
bar1.setValue("gnu");
foo.setBar1(bar1);
bar2 = new BarExpression();
bar2.setExpression("bean.property * 2");
foo.setBar2(bar2);
//
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
StringWriter w = new StringWriter();
mapper.writeValue(w, foo);
System.out.println(w.toString());
}
gives the expected result:
{
"bar1" : {
"#type" : "de.mit.jackson.BarLiteral",
"value" : "gnu",
"type" : "java.lang.String"
},
"bar2" : {
"#type" : "de.mit.jackson.BarExpression",
"expression" : "bean.property * 2"
}
}
The question is now: I want to improve user experience when handwriting this "DSL" by supporting "primitive shortcuts" for the typed "Bar..." classes like this
{
"bar1" : "gnu",
"bar2" : "#{bean.property * 2}"
}
The solution that came closest was using a converter on Foo#bar1 and Foo#bar2, checking for either String or "Bar" input, but this solution requires decoration of every attribute definition.
Creating a deserializer with a comparable behavior did not work, as the #JsonTypeInfo is not compatible in the sense that i can have a #JsonDeserialize implementation that will check for a String event and then delegate to the standard #JsonTypeInfo process. The #JsonTypeInfo standard will check only for the #type and then delegate back to the (subtype) deserializer which is again my wrapper implementation.
The required process is
if input event is string {
parse and return string input
} else {
activate #type parsing delegate;
after #type parsing activate standard BeanDeserializer
(**not** my implementation)
}
Is there another hook i am missing?

Working example of a Singleton

In C#, I want to implement Singletons to provide data in one thread to many other threads.
I have decided to use this lazy form of Singleton from Jon Skeet (thanks, Jon!):
public sealed class Singleton
{
Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
So far, so good. ... but how does one use that?
What I want to do is share a single instance of the following data:
public bool myboolean = false ;
public double mydoubles[] = new double[128,3] ;
public IntPtr myhandles[] = new IntPtr[128] ;
How do I declare and reference these data as Singletons?
I also need them to be referenceable across different namespaces.
Many thanks!
// thread-safety
public sealed class Singleton
{
private static Singleton instance = null;
private static readonly object padlock = new object();
private bool myboolean = false;
private double[,] mydoubles = new double[128, 3];
private IntPtr[] myhandles = new IntPtr[128];
Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
}
and to access
//Singleton.Instance.myboolean
//Singleton.Instance.mydoubles
//Singleton.Instance.myhandles

How to implement EF Code First and WCFDataService

A bit of history first. I created a EF Code First Library that contains POCO Objects as my Models, a generic DataProvider that inherits from DbContext, generic Repostory that implements the generic DataProvider, and a generic Service that implements the repository. I have used this library successfully in WPF (MVVM), ASP.Net, Window Forms, and ASP MVC applications.
For this discussion I will reference the Company Model
From the top down, I create a Service class called CompanyService that inherits from a base Service Class. The CompanyService class contains all of the business logic for the Company Model. This class uses the Repository class to perform the CRUD operations. The Repository then encapsulates all the DataProvider class operations.
I have done some research on using EF with WCFDataService, but I can't get my head around how to implement my library with it, particulary when it comes to overriding the CreateDataSource() Method.
It may be that I should just use a WCF Service instead, maybe I'm not understanding the purpose of the WCFDataService.
I have listed partial code for the classes involved:
public class CompanyService : ServiceBase<Company> ,ICompanyService
{
public Company GetCompanyByFolderId(string eFolderId)
{
return (Company)GetModelByFolderId(eFolderId);
}
}
public abstract class ServiceBase<TModel> : IService<TModel> where TModel : class, IModel
{
private IDataProvider _dataProvider;
public IDataProvider DataProvider
{
get
{
if (_dataProvider == null)
{
string connectionStringName = Properties.Settings.Default.DataProvider;
bool enableLazyLoading = true;
_dataProvider = new DataProvider(connectionStringName, enableLazyLoading);
}
return _dataProvider;
}
set
{
_dataProvider = value;
}
}
private IRepository<TModel> _repository;
public IRepository<TModel> Repository
{
get
{
if (_repository == null)
{
_repository = new Repository<TModel>(DataProvider);
}
return _repository;
}
set
{
_repository = value;
}
}
public TModel GetModelByFolderId(String folderId)
{
return GetTable().FirstOrDefault(o => o.EFolderid == folderId);
}
public virtual IQueryable<TModel> GetTable()
{
return Repository.GetTable();
}
}
public class Repository<TModel> : IRepository<TModel> where TModel : class, IModel
{
private IDataProvider _dataProvider;
public Repository(IDataProvider dataProvider)
{
_dataProvider = dataProvider;
}
private IDbSet<TModel> DbSet
{
get
{
return _dataProvider.Set<TModel>();
}
}
public IQueryable<TModel> GetTable()
{
return _dataProvider.GetTable<TModel>();
}
}
public class DataProvider : DbContext, IDataProvider
{
public DataProvider()
{
}
public DataProvider(string connectionStringName, bool enableLazyLoading = true)
: base(connectionStringName)
{
Configuration.LazyLoadingEnabled = enableLazyLoading;
//Configuration.ProxyCreationEnabled = false;
}
public new IDbSet<TModel> Set<TModel>() where TModel : class
{
return base.Set<TModel>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CompanyMapping());
base.OnModelCreating(modelBuilder);
}
public IQueryable<TModel> GetTable<TModel>() where TModel : class
{
return Set<TModel>().AsQueryable();
}
}
Then my Test looks something like this:
[TestClass()]
public class CompanyServiceTest
{
[TestMethod()]
public void GetCompanies()
{
CompanyService target = new CompanyService();
IQueryable<Company> companies = target.GetTable();
Assert.IsNotNull(companies);
}
[TestMethod()]
public void GetCompanyByFolderId()
{
CompanyService target = new CompanyService();
Company company = target.GetCompanyByFolderId("0000000000000000000000000172403");
Assert.IsNotNull(company);
}
}

Abstraction is changed?

My question is, how to redesign abstract factory.
For example, I get next abstraction of vehicles:
interface IEngine { int Power(); }
class Gasoline : IEngine { public int Power() {return 150; }}
class Diesel : IEngine { public int Power() { return 50; }}
interface IFrame { string Name(); }
class Boxed : IFrame { public string Name() { return "Boxed frame"; }}
class Hat : IFrame { public string Name() { return "Hat frame"; }}
interface TransportFactory {
IEngine CreateEngine();
IFrame CreateChassis();
}
class TrailerCar : TransportFactory {
public IEngine CreateEngine() { return new Diesel(); }
public IFrame CreateChassis() { return new Boxed(); }
}
class PrivateCar : TransportFactory {
public IEngine CreateEngine() { return new Gasoline(); }
public IFrame CreateChassis() { return new Hat(); }
}
Now, I can instantiate private or trailer car.
Some one suggest me changes: engine for trailers cars can by turbo or hybrid. Only for trailers! For private car diesel and gasoline engines still usual diesel engine.
So, if i do changes:
public enum EngineType { Hybrid, Turbo, }
interface TransportFactory
{
IEngine CreateEngine(EngineType t);
IFrame CreateChassis();
}
and i can add classes:
class GasolineHybrid : IEngine
{
public int Power()
{
return 70;
}
}
class GasolineTurbo : IEngine
{
public int Power()
{
return 170;
}
}
class DieselHybrid : IEngine
{
public int Power()
{
return 60;
}
}
class DieselTurbo : IEngine
{
public int Power()
{
return 98;
}
}
it is good, but (!!!) private car nothing to do with it!!!
What kind of design can i use? Old abstraction get incorrect?
Thanks a lot!!!
How about:
class GasolineHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineHybrid();
}
...
}
class GasolineTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineTurbo();
}
...
}
class DieselHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselHybrid();
}
...
}
class DieselTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselTurbo();
}
...
}
The idea behind spawning numerous classes is to remove client's ability to do wrong choice. Since you said hybrid and turbo engines do not make sense for private cars, then keeping
IEngine CreateEngine(EngineType t);
will require from private car factory additional efforts to refuse incorrect arguments.
I am not sure did you mean it, but class names suggest that cars are products of factory. In classic relation it will be factory --produce--> product. It is kinky and fun how you put it via generalization, but could be hardly recognizable by others. The beauty of patterns is that once you hear its one word name, then you feel confident about all the internals the implementation could imply.
There is pattern Builder. Would it be more suitable name for your design?
Remember that parameters need not be part of the interface, they can be passed to the constructor of the implementation. So you can still keep your old interface:
interface TransportFactory
{
IEngine CreateEngine();
IFrame CreateChassis();
}
but pass the EngineTypeto the TrailerCar constructor:
class TrailerCar : TransportFactory {
private readonly EngineType engineType;
public TrailerCar(EngineType engineType)
{
this.engineType = engineType;
}
public IEngine CreateEngine()
{
if (engineType == EngineType.Hybrid) return new DieselHybrid();
else return new DieselTurbo();
}
public IFrame CreateChassis() { return new Boxed(); }
}

NHibernate: Persist Reference to Interface with Multiple Contrete Classes

I have a 1-to-many relationship between the RestorableEnvironment and IBaselineEntity objects: a given RestorableEnvironment will have one and only one IBaselineEntityobject, but each IBaselineEntity object may be tied to 0-n RestorableEnvironment objects. However, IBaselineEntity is implemented in one of two ways: via a file or via a database. My classes are (generally) like:
public interface IBaselineEntity
{
BaselineImage BuildImage();
//Remainder of interface
}
public class BaselineFile : IBaseline
{
//implementation
}
public class BaselineDatabase : IBaseline
{
//implementation
}
public class RestorableEnvironment
{
public IBaselineEntity BaselineEntity { get; set; }
//Remainder of class
}
NHibernate needs the concrete implementation of the IBaselineEntity in the references statement. To handle that, I have updated RestorableEnvironment to:
public class RestorableEnvironment
{
public IBaselineEntity BaselineEntity
{
get { return BaselineDatabase ?? BaselineFile; }
set
{
BaselineFile = value as BaselineFile;
BaselineDatabase = value as BaselineDatabase;
}
}
private BaselineFile _baselineFile;
public BaselineFile BaselineFile
{
get { return _baselineFile; }
protected set
{
_baselineFile = value;
if (value != null)
BaselineDatabase = null;
}
}
private BaselineDatabase _baselineDatabase;
public BaselineDatabase BaselineDatabase
{
get { return _baselineDatabase; }
protected set
{
_baselineDatabase= value;
if (value != null)
BaselineFile = null;
}
}
// Remainder of class
}
Now that I have concrete classes, I can now map in NHibernate, but this feels like a hack. Are there any suggestions for an improvement?
map it as any reference
using fluentmapping
// ClassMap<RestorableEnvironment>
RestorableEnvironmentMap()
{
ReferenceAny(e => e.BaselineEntity)
.EntityIdentifierColumn("entirtyid")
.EntityTypeColumn("entitytype")
.IdentityType<int>()
.MetaType<string>()
.AddMetaValue<E1>("e1")
.AddMetaValue<E2>("e2");
}